home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGBLER
/
MATHASM.LZH
/
PLOT.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-11-04
|
15KB
|
508 lines
PAGE 255,132
;-------------------------------------------------------------
;
; orline.asm
; orpt.asm
;
; written by Bruce A. Smith 7/24/84
;
;-------------------------------------------------------------
;
; The two procedures here plot a point or draw a line on the
; medium resolution screen of the IBM PCjr or IBM PC. The
; line drawing routine uses self-modifying code. They both
; are written to OR the color bits onto the screen. The
; objective of writing these routines was to achieve as much
; speed performance as possible with the 8088 microprocessor
; used in these machines. The line drawing routine is
; approximately three times faster than the one listed in the
; BLUEBOOK OF ASSEMBLY ROUTINES FOR THE IBM PC & XT by
; Christopher Morgan. It is also three times faster than the
; line drawing routine used in the ROM BASIC on the PCjr.
; The point plotting routine is a little more difficult to
; compare because the overhead of the call and the computation
; for the next point become significant. In performance tests
; it plotted points half again as fast as the routine in the
; previously mentioned book by Christopher Morgan and in
; spite of the overhead it performed four times faster than
; the ROM BIOS point plotting routines. So this point plotting
; routine is probably about five times faster than the ROM BIOS.
;
;------------------------------------------------------------
; REFERENCES
;
; Foley, James d. and Andries Van Dam, Fundamentals of Interactive
; Computer Graphics, Addison-Wesley, Reading, MA, 1982.
;
; Morgan, Christopher L., Bluebook of Assembly Routines for
; the IBM PC & XT, The Waite Group, New York, NY, 1984.
;
;------------------------------------------------------------
;
DGROUP GROUP DATA
DATA SEGMENT WORD PUBLIC 'DATA'
ASSUME DS:DGROUP
PUBLIC COLOR,X1,X2,Y1,Y2
;
; the order and type of declaration is important here
;
y2 dw 0
x2 dw 0
y1 dw 0
x1 dw 0
color db 0
;
; color = color * 4 + 1, color 0 == mask
;
ctableh db 03Fh,0CFh,0F3h,0FCh
db 040h,010h,004h,001h
db 080h,020h,008h,002h
db 0C0h,030h,00Ch,003h
;
fakedw = 1000h
;
DATA ENDS
;
;------------------------------------------------------------
;
PGROUP GROUP PROG
PROG SEGMENT BYTE PUBLIC 'PROG'
PUBLIC ORLINE,ORPT
ASSUME CS:PGROUP
;
;-------------------------------------------------------------
;
; orline.asm
;
;------------------------------------------------------------
;
; ROUTINE TO OR A LINE ONTO MEDIUM RESOLUTION SCREEN
;
; uses Bresenham's algorithm
;
orline proc near
push bp ; save calling bp
; only reg needed to save for 'C'
push ds ; save ds
; ------------------------------
; get x & y values
mov si,OFFSET y2 ; addr y2
lodsw ; ax = y2
xchg ax,dx ; dx = y2
lodsw ; ax = x2
xchg ax,di ; di = x2
lodsw ; ax = y1
xchg ax,cx ; cx = y1
lodsw ; ax = x1
mov bx,si ; bx = addr color
xchg ax,si ; si = x1
;
cmp si,di ; cmp x1,x2
jle swapxy ; skip if (x1<=x2)
xchg cx,dx ; (x1>x2): swap y1,y2
xchg si,di ; swap x1,x2
swapxy:
;
; ............................................
; | H | L |
; -----------------------------------------------
; ax | | |
; -----------------------------------------------
; bx | addr color |
; -----------------------------------------------
; cx | 0 | y1 | if ( x1 > x2 )
; ----------------------------------------------- swap (x1,y1) with
; dx | 0 | y2 | (x2,y2)
; ----------------------------------------------- ie.
; si | x1 | xchg cx,dx
; ----------------------------------------------- xchg si,di
; di | x2 |
; -----------------------------------------------
; bp | |
; ----------------------------------,=-----------
;
;
; ch = deldy = (y1>y2) ? -80 : 80
; dx = |y2-y1|
sub dx,cx ; y2-y1
mov al,80 ; deldy = 80
jge ydown ; skip if (y1<=y2)
neg dx ; |y2-y1|
neg al ; deldy = -1
ydown:
sub di,si ; x2-x1
; di = |x2-x1|
;
; ............................................
; | H | L |
; ----------------------------------------------- al=80
; ax | | (y1>y2)? -80: 80 | dx-cx = y2-y1
; ----------------------------------------------- if neg (y1>y2)
; bx | addr color | neg dx =|y2-y1|
; ----------------------------------------------- al=-80
; cx | 0 | y1 |
; ----------------------------------------------- deldy = al
; dx | 0 | absdy = |y2-y1| |
; -----------------------------------------------
; si | x1 |
; ----------------------------------------------- di-si
; di | absdx = x2-x1 | = |x2-x1|
; -----------------------------------------------
; bp | |
; -----------------------------------------------
;
;
cmp di,dx ; absdx,absdy
lahf
jnl minmax ; skip if (absdx>=absdy)
xchg di,dx
minmax:
; dx = dmin
; di = dmax
;
; ............................................
; | H | L | if (absdx < absdy)
; ----------------------------------------------- cmp di,dx lahf
; ax | flags absdx,absdy| deldy | jnl -
; ----------------------------------------------- swap(absdx,absdy)
; bx | addr color | xchg di,dx
; ----------------------------------------------- -:
; cx | 0 | y1 |
; -----------------------------------------------
; dx | 0 | dmin |
; -----------------------------------------------
; si | x1 |
; -----------------------------------------------
; di | dmax |
; -----------------------------------------------
; bp | |
; -----------------------------------------------
;
;
xchg ax,bp ; bp=flags(absdx,absdy) & deldy
;
; ROUTINE TO FIND INITIAL Y-ADDR, X-ADDR, AND ROTATED COLOR
;
; multiply y-coord by bytes per row and adjust for even/odd lines
ror cl,1 ; adjust odd/even
mov ax,cx ; ax = cx = adj y-coord
and al,7Fh ; page mask
sal cx,1 ; times 2
sal cx,1 ; times 4
add cx,ax ; y-coord times 5
sal cx,1 ; times 10
sal cx,1 ; times 20
sal cx,1 ; times 40
sal cx,1 ; times 80
;
; ............................................
; | H | L |
; -----------------------------------------------
; ax | 0 | |
; -----------------------------------------------
; bx | addr color = addr ctableh-1 |
; -----------------------------------------------
; cx | y-addr |
; -----------------------------------------------
; dx | 0 | dmin |
; -----------------------------------------------
; si | x1 |
; -----------------------------------------------
; di | dmax |
; -----------------------------------------------
; bp | flags absdx,absdy| deldy |
; -----------------------------------------------
;
;
; compute the rotated mask and color
; bx = ctableh-1 = addr color
mov al,3 ; pixel position mask
and ax,si ; just the bit count into the index
add al,[bx] ; pixel position + color (* 4 + 1)
xlat ; look up the masks al=[al+bx]
;
mov bx,0B800H ; disp seg base addr
mov ds,bx ; ds = display base addr
;
; al = rotated color
; cx = y-addr offset
; ds = display addr
;
; ............................................
; | H | L |
; -----------------------------------------------
; ax | 0 | rotated color |
; -----------------------------------------------
; bx | | |
; -----------------------------------------------
; cx | y-addr |
; -----------------------------------------------
; dx | 0 | dmin |
; -----------------------------------------------
; si | x1 |
; -----------------------------------------------
; di | dmax |
; -----------------------------------------------
; bp | flags absdx,absdy| deldy |
; -----------------------------------------------
;
;
sal dx,1 ; dx = delse = dmin * 2
xchg cx,di ; cx = dmax, di = y-addr
xchg ax,dx ; ax=delse, dx=rotated color
xchg ax,bp ; ax=flags(absdx,absdy), bp=delse
;
; ............................................
; | H | L |
; -----------------------------------------------
; ax | flags absdx,absdy| deldy |
; -----------------------------------------------
; bx | | |
; -----------------------------------------------
; cx | dmax |
; -----------------------------------------------
; dx | 0 | rotated color |
; -----------------------------------------------
; si | x1 |
; -----------------------------------------------
; di | y-addr |
; -----------------------------------------------
; bp | dmin * 2 = delse |
; -----------------------------------------------
;
;
sahf ; cmp absdx,absdy
pushf
;
cbw ; ax = deldy
mov cs:delsy,ax ; save deldy
mov cs:deldy,ax
mov cs:deldy2,ax
mov bx,di ; bx = y-addr
or ax,ax
js negdeldy ; if deldy<0 jmp
;
test bh,20H ; is page bit set?
jz toggle ; skip to toggle page
;
add bx,ax ; add deldy to y-addr
jmp toggle ; skip to toggle page
negdeldy:
test bh,20H ; is page bit set?
jnz toggle ; skip to toggle page
;
add bx,ax ; add deldy to y-addr
toggle:
xor bh,20H ; flip page bit
; bx = next y-addr
;
; ............................................
; | H | L |
; -----------------------------------------------
; ax | | |
; -----------------------------------------------
; bx | y-addr (next) |
; -----------------------------------------------
; cx | dmax |
; -----------------------------------------------
; dx | 0 | rotated color |
; -----------------------------------------------
; si | x1 |
; -----------------------------------------------
; di | y-addr |
; -----------------------------------------------
; bp | dmin * 2 = delse |
; -----------------------------------------------
;
;
xchg ax,bp ; ax = dmin * 2 = delse
mov cs:delse,ax ; save delse
mov cs:delse2,ax ; save delse
sub ax,cx ; ax = dmin * 2 - dmax = d
mov bp,ax ; bp = d = error term
sub ax,cx ; ax = dmin * 2 - dmax * 2
mov cs:delde,ax ; save delde
mov cs:delde2,ax ; save delde
;
xchg ax,bx ; ax = next y-addr
;
; figure x-coord address
mov bx,si ; get x-coordinate
sar bx,1 ; divide
sar bx,1 ; by 4
; bx = x-addr offset
;
; ............................................
; | H | L |
; -----------------------------------------------
; ax | y-addr (next) |
; -----------------------------------------------
; bx | x-addr |
; -----------------------------------------------
; cx | loop count |
; -----------------------------------------------
; dx | | rotated color |
; -----------------------------------------------
; si | x value |
; -----------------------------------------------
; di | y-addr |
; -----------------------------------------------
; bp | error term |
; -----------------------------------------------
;
;
popf ; cmp absdx,absdy
jns delsx2 ; if (absdx>=absdy) goto delsx2
;
; -----------------------------------------------
; delsx = 0 (absdx < absdy)
;
or [bx][di],dl ; or disp with color (plot point)
jcxz lineexit ; quit when cx=0
or bp,bp ; set bp flags
jge diagonal ; if bp>=0 jmp
;
; case for straight move
straight:
xchg ax,di ; every other for page adj
delsy = $+1
add ax,fakedw ; ++y
;
or [bx][di],dl ; or disp with color (plot point)
dec cx ; --loop counter
jz lineexit ; quit when cx=0
;
delse = $+2
add bp,fakedw ; update error term
js straight ; if bp<0 goto straight
;
; case for diagonal move
diagonal:
inc si ; ++x value
mov bx,si ; bx = x value
sar bx,1
sar bx,1 ; bx = x addr offset
;
ror dl,1 ; adjust color position
ror dl,1
;
xchg ax,di ; every other for page adj
deldy = $+1
add ax,fakedw ; ++y
;
or [bx][di],dl ; or disp with color (plot point)
dec cx ; --loop counter
jz lineexit ; quit when cx=0
;
delde = $+2
add bp,fakedw ; update error term
js straight ; if bp<0 goto straight
jmp diagonal ; if bp>=0 goto diagonal
;
; -----------------------------------------------
delsx2:
; delsx = 1 (absdx >= absdy)
;
or [bx][di],dl ; or disp with color (plot point)
jcxz lineexit ; quit when cx=0
or bp,bp ; set bp flags
jge diagonal2 ; if bp>=0 jmp
;
; case for straight move
straight2:
inc si ; ++x value
mov bx,si ; bx = x value
sar bx,1
sar bx,1 ; bx = x addr offset
;
ror dl,1 ; adjust color position
ror dl,1
;
or [bx][di],dl ; or disp with color (plot point)
dec cx ; --loop counter
jz lineexit ; quit when cx=0
;
delse2 = $+2
add bp,fakedw ; update error term
js straight2 ; if bp<0 goto straight
;
; case for diagonal move
diagonal2:
inc si ; ++x value
mov bx,si ; bx = x value
sar bx,1
sar bx,1 ; bx = x addr offset
;
ror dl,1 ; adjust color position
ror dl,1
;
xchg ax,di ; every other for page adj
deldy2 = $+1
add ax,fakedw ; ++y
;
or [bx][di],dl ; or disp with color (plot point)
dec cx ; --loop counter
jz lineexit ; quit when cx=0
;
delde2 = $+2
add bp,fakedw ; update error term
js straight2 ; if bp<0 goto straight
jmp diagonal2 ; if bp>=0 goto diagonal
;
; -----------------------------------------------
lineexit:
pop ds ; restore ds
pop bp ; restore calling bp
ret
;
orline endp
;
;------------------------------------------------------------
;
; orx<.asm
;
;------------------------------------------------------------
;
; ROUTINE TO OR A POINT ONTO MEDIUM RES COLOR SCREEN
;
orpt proc near
;
; get initial values for x and y
mov si,OFFSET y1 ; addr y1
lodsw ; ax = y1
;
; multiply y-coord by bytes per row and adjust for even/odd lines
ror al,1 ; adjust odd/even
;
mov dx,0B87FH ; disp addr and page mask
and dl,al ; mask page bit, disp + y.coord
sal ax,1 ; times 32
sal ax,1 ; times 64
add dx,ax ; addr disp seg + y-coord times 5 (80)
;
; compute x-coord address offset
lodsw ; ax = x1
mov di,ax ; get x-coordinate
sar di,1 ; divide
sar di,1 ; by 4
;
; compute the rotated mask and color
and al,3 ; just the bit count into the index
add al,[si] ; pixel position + color (* 4 + 1)
mov bx,si ; bx = ctableh - 1
mov si,ds ; save ds
xlat ; look up the masks al=[al+bx]
;
mov ds,dx ; set seg to disp + y-addr
or [di],al ; or the byte with the color
;
mov ds,si ; restore ds
ret
;
orpt endp
;
;------------------------------------------------------------
;
PROG ENDS
END